package org.example;
import org.example.loadBalancers.LoadBalanceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;


//网关类 与内部调用不一样  这个是前缀替换成服务名 然后再服务名负载均衡 替换真实url     内部调用直接是服务名负载均衡 替换真实url  这里不多写了 具体在rpc那里写

public class MyGatewayFilter implements Filter {

    @Autowired
    RestTemplate restTemplate;


    @Autowired
    LoadBalanceContext loadBalanceContext;


    //核心方法 把请求直接转发到服务 如果没有则返回bad gateway
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI();  // 获取整个请求路径
        String[] pathParts = requestURI.split("/");      // 将路径按 "/" 分割
        System.out.println(Arrays.toString(pathParts));

        if (pathParts.length > 1) {
            String serviceName = pathParts[1];           // 第一个路径段，即服务名

            //如果第一个路径段为notify开头的则跳过
            if (serviceName.startsWith("notify")) {
                chain.doFilter(request, response);
                return;
            }

            //这里不封装负载均衡 因为 要配合网关的  相当于有两步：
            // 外部转内部服务名： 绝大部分 都在这里    内部服务名转实际url 很小一部分 这里不想写了
            ServiceInstance serviceInstance = loadBalanceContext.getServiceInstance(serviceName);

            if (serviceInstance!=null) {

                String serviceAddress = serviceInstance.getIp()+":"+ serviceInstance.getPort();

                // 如果路径有多个部分，拼接从 pathParts[1] 到最后的部分
                StringBuilder fullPath = new StringBuilder();
                for (int i = 2; i < pathParts.length; i++) {
                    fullPath.append("/");  // 只在不是第一个部分时添加 "/"
                    fullPath.append(pathParts[i]);
                    System.out.println(pathParts[i]);
                }
                //得到实际请求路径
                String targetUrl ="http://"+serviceAddress +fullPath;

                System.out.println("转发请求: "+targetUrl);





                HttpServletResponse httpResponse = (HttpServletResponse) response;

                // 设置请求头
                HttpHeaders headers = new HttpHeaders();

                // 创建 HttpEntity（包含请求体和请求头）
                HttpEntity<String> entity = new HttpEntity<>(null, headers); // 请求体根据需要进行填充

                // 发起 HTTP 请求到目标服务
                ResponseEntity<String> responseEntity = restTemplate.exchange(targetUrl, HttpMethod.valueOf(httpRequest.getMethod()), entity, String.class);

                // 获取目标服务的响应内容
                String responseContent = responseEntity.getBody();

                // 设置客户端响应的内容类型
                httpResponse.setContentType(Objects.requireNonNull(responseEntity.getHeaders().getContentType()).toString());
                httpResponse.setStatus(responseEntity.getStatusCodeValue()); // 设置目标服务的响应状态码

                // 将目标服务的响应内容写入客户端的响应
                if (responseContent != null) {
                    httpResponse.getWriter().write(responseContent);
                }


                return;
            }

        }

            // 返回 502 错误并重定向到自定义错误页面
        ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_BAD_GATEWAY);
        response.getWriter().write("<h1 style='text-align:center;'>502 Bad Gateway</h1>");


    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
